package com.cgg.stock.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cgg.stock.common.exception.InvalidVerifyCodeException;
import com.cgg.stock.common.exception.UsernameAndPasswordErrorException;
import com.cgg.stock.common.exception.VerifyCodeErrorException;
import com.cgg.stock.common.pojo.Optional;
import com.cgg.stock.common.pojo.User;
import com.cgg.stock.common.util.TokenUtil;
import com.cgg.stock.user.mapper.OptionalMapper;
import com.cgg.stock.user.mapper.UserMapper;
import com.cgg.stock.user.service.UserService;
import com.cgg.stock.user.util.PasswordUtils;
import com.cgg.stock.user.util.UserContext;
import com.cgg.stock.user.vo.LoginBean;
import com.cgg.stock.user.vo.RegisterBean;
import com.cgg.stock.user.vo.dto.LoginUserDTO;
import com.cgg.stock.user.vo.dto.UserInfoDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    UserMapper userMapper;

    @Autowired
    OptionalMapper optionalMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public String login(LoginBean loginBean) throws Exception {
        /*
        1. 得到Session域验证码,  与用户传递的验证码进行对比
        2. 如果验证码不通过, 响应错误信息
        3. 如果验证码通过, 进行用户名,密码验证   md5
        4. 根据用户名查询用户,  如果用户存在, 再进行密码验证,
        5. 如果用户不存在,或者密码错误, 响应错误信息
        6. 如果用户存在,而且密码一样, 登录成功, 响应token(用户名), 把用户保存到session
         */

        //第一个问题? 业务层得到Session中的数据  session相关操作 封装到UserContext
        String verifyCode = UserContext.getVerifyCode();
        System.out.println("获取的验证码："+verifyCode);
        String str = loginBean.getCaptcha();
        System.out.println("login的验证码："+str);
        if(StringUtils.isEmpty(verifyCode)){  //说明session不存在验证
            throw new InvalidVerifyCodeException();
        }
        if(!verifyCode.equals(loginBean.getCaptcha())){ //用户输入的验证码与session验证码不一样
            throw new VerifyCodeErrorException();
        }
        String username = loginBean.getUsername();
        Long account = Long.parseLong(loginBean.getAccount());
        String password = loginBean.getPassword();

        //根据用户名查询
        User user = queryUserByAccount(account);

        //判断使用有对象   用户名或者密码错误
        if (user!=null){//有该用户
            //判断密码是否一样
            //if (PasswordUtils.verify(password,user.getPassword())){ //true 表示密码正确
                if(password.equals(user.getPassword())){
                //登录成功
                // 把用户保存到session
                //UserContext.setLoginUser(user);

                //把登录信息保存到Redis中
                // key设计?   loginUser:token   value: LoginUserDTO对象(hash)
                //使用jwt生成token, 使用UUID生成Token

                String token = TokenUtil.randomToken();
                String key = "loginUser:"+token;

                //把User转换为LoginUserDTO
                LoginUserDTO loginUserDTO = BeanUtil.copyProperties(user, LoginUserDTO.class);

                //把LoginUserDTO对象转换为map集合
                Map<String, Object> map = BeanUtil.beanToMap(loginUserDTO, false, true);

                //把登录信息保存到redis中，以Hash的形式
                redisTemplate.opsForHash().putAll(key,map);
                //设置有效时间：30分钟： 模拟与session的有效时间一样 30分钟未使用
                redisTemplate.expire(key,30, TimeUnit.MINUTES);
                 System.out.println("登录成功");
                return token;
            }
        }
        throw new UsernameAndPasswordErrorException();

    }

    @Override
    @Transactional
    public int register(RegisterBean registerBean) {

        System.out.println(registerBean);

        if (registerBean!=null){
            Long account = registerBean.getAccount();
            //根据用户名查询
            User user = queryUserByAccount(account);
            if(user!=null){
                return 500;
            }
            User user1 = BeanUtil.copyProperties(registerBean,User.class);
            userMapper.insert(user1);
            return 200;
        }
       return 200;



    }

    @Override
    public User queryUserByAccount(Long userAccount) {
        return userMapper.selectByAccount(userAccount);
    }


    @Override
    @Cacheable(value = "user",key = "'names'")
    public User queryByName(String username) {

        //1。创建一个条件构造器
        //QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //2.设置条件 eq(boolean 是否执行条件， 列名， 值)
        //queryWrapper.eq("username",username);
        lambdaQueryWrapper.eq(User::getUserName,username);

        return userMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public BigDecimal getAccountBalance(Long account){

        return userMapper.selectBalance(account);

    }

    @Override
    @Transactional
    public int updateAccountBalance(Long account, BigDecimal amount, int count){

        BigDecimal accountBalance = userMapper.selectBalance(account).add(amount.multiply(BigDecimal.valueOf(count)));

        return userMapper.updateBalance(account,accountBalance);
    }

    @Override
    public UserInfoDTO getUserInfo(String account) {

        QueryWrapper queryWrapper = new QueryWrapper();

        queryWrapper.eq("account",account);

        User user = userMapper.selectOne(queryWrapper);

        UserInfoDTO userInfoDTO = new UserInfoDTO();
        BeanUtils.copyProperties(user,userInfoDTO);

        QueryWrapper queryWrapperOprional = new QueryWrapper();
        queryWrapperOprional.eq("user_id",user.getId());

        List<Optional> optional = optionalMapper.selectList(queryWrapperOprional);


        StringBuffer sb = new StringBuffer();

        for (Optional o : optional) {
            sb.append("sh").append(o.getStockId()).append(",");
        }
        //删除最后一个' , ';
        sb.deleteCharAt(sb.length()-1);
        userInfoDTO.setOptional(sb.toString());


        return userInfoDTO;
    }


}
